package graphics.fingerprint;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;

import android.util.Log;

import command.Command;
import command.SimpleActionCommand;
import command.SimpleTouchCommand;

public class CommandPusher {
	private LinkedBlockingQueue<Command> commands = new LinkedBlockingQueue<Command>();
	private Socket socket;
	private Sender sender;

	public void startSend(Socket s) {
		this.socket = s;
		try {
			DataOutputStream out = new DataOutputStream(
					new BufferedOutputStream(socket.getOutputStream()));
			this.sender = new Sender(out);
			this.sender.start();
		} catch (IOException e) {
			Log.d("Debug&Info", "sender failed when start");
			e.printStackTrace();
		}
	}

	public void stopWork() throws IOException {
		if (sender != null && sender.isAlive()) {
			this.sender.stop();
		}
		this.socket.getOutputStream().close();
	}

	class Sender extends Thread {
		private DataOutputStream dos;

		public Sender(DataOutputStream out) {
			this.dos = out;
		}

		public void run() {
			while (true) {
				synchronized (commands) {
					while (commands.isEmpty()) {
						try {
							commands.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					send(commands.poll());
				}
			}
		}

		public void send(Command c) {
			try {
				if (c instanceof SimpleTouchCommand) {
					sendSimpleTouchCommand(c);
				} else if (c instanceof SimpleActionCommand) {
					sendSimpleActionCommand(c);
				} else {
					sendMessage(c);
				}
			} catch (IOException e) {
				e.printStackTrace();
				Log.e("Debug&Info", e.toString());
				System.exit(0);
			}
		}

		private void sendSimpleTouchCommand(Command c) throws IOException {
			dos.writeInt(c.getType());
			SimpleTouchCommand stc = (SimpleTouchCommand) c;
			dos.writeInt(stc.getKey());
			dos.writeInt((int) stc.getX());
			dos.writeInt((int) stc.getY());
			dos.flush();
		}

		private void sendMessage(Command c) throws IOException {
			dos.writeInt(c.getType());
			PrintWriter writer = new PrintWriter(new BufferedWriter(
					new OutputStreamWriter(dos)), true);
			writer.println(c);
			return;
		}

		private void sendSimpleActionCommand(Command c) throws IOException {
			dos.writeInt(c.getType());
			dos.flush();
			return;
		}
	}

	public void pushCommand(Command command) {
		synchronized (commands) {
			try {
				commands.put(command);
				commands.notify();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
